#include "httphelper.h"
#include <QDebug>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
#include <mutex>
#include <QUrl>

std::unique_ptr<HttpHelper> HttpHelper::instance_ = nullptr;
#define SERVER_URL "http://10.200.14.253:8083/"



//http不是同步请求，而是异步请求
HttpHelper::HttpHelper(QObject *parent)
    : QObject(parent)
    ,networkManager(new QNetworkAccessManager(this))//初始化列表
{
    requestAddrs[REGISTER] = QString(SERVER_URL) + "user/register";
    requestAddrs[LOGIN] = QString(SERVER_URL) + "user/login";
    requestAddrs[LOGINOUT] = QString(SERVER_URL) + "user/loginout";
    requestAddrs[MEDIALIST] = QString(SERVER_URL) + "media/list";
    requestAddrs[ADDMEDIA] = QString(SERVER_URL) + "media/add";
    requestAddrs[EDITMEDIA] = QString(SERVER_URL) + "media/edit";
    requestAddrs[REMOVEMEDIA] = QString(SERVER_URL) + "media/remove";

    connect(networkManager,&QNetworkAccessManager::finished,this,&HttpHelper::onReplyFinished);


}

//这段代码是 C++11 中实现线程安全单例模式（Singleton） 的经典写法
//结合了 std::once_flag 和 std::call_once 来确保在多线程环境下只创建一个 HttpHelper 实例
HttpHelper *HttpHelper::instance()
{
    static std::once_flag flag;//1. 静态的 once_flag 变量
    std::call_once(flag,[&](){ // 2. 调用 call_once，确保 lambda 只执行一次
       instance_.reset(new HttpHelper()); // 3. 创建单例实例
    });
    return instance_.get(); // 4. 返回实例指针
}

void HttpHelper::slot_GetmediaInfo()
{
    if(token.isEmpty()){
        qWarning()<<"Cannot get media list:Token is empty!";
        emit sig_Operator(MEDIALIST,false);
        return;
    }
    sendRequest(MEDIALIST,false);

}

void HttpHelper::slot_Regeister(const QVariantMap &infomap)
{
    QJsonObject paramsObj;
    paramsObj[""] = QJsonObject();
    QJsonObject rootObj;
    rootObj["createTime"] = "";
    rootObj["updateTime"] = "";
    rootObj["params"] = paramsObj;
    rootObj["userId"] = 0;
    rootObj["username"] = infomap["username"].toString();
    rootObj["nickname"] = infomap["nickname"].toString();
    rootObj["password"] = infomap["password"].toString();
    //QJsonObject转为jsondocument
    QJsonDocument doc(rootObj);
    QByteArray jsondata = doc.toJson(QJsonDocument::Compact);
    sendRequest(REGISTER,true,jsondata);
}

void HttpHelper::slot_Login(const QVariantMap &infomap)
{
    QJsonObject paramsObj;
    paramsObj[""] = QJsonObject();
    QJsonObject rootObj;
    rootObj["createTime"] = "";
    rootObj["updateTime"] = "";
    rootObj["params"] = paramsObj;
    rootObj["userId"] = 0;
    rootObj["username"] = infomap["username"].toString();
    rootObj["nickname"] = infomap["nickname"].toString();
    rootObj["password"] = infomap["password"].toString();
    //QJsonObject转为jsondocument
    QJsonDocument doc(rootObj);
    QByteArray jsondata = doc.toJson(QJsonDocument::Compact);
    sendRequest(LOGIN,true,jsondata);

}

void HttpHelper::slot_LoginOut(const QVariantMap &infomap)
{
    QJsonObject rootObj;
    QJsonDocument doc(rootObj);
    QByteArray jsondata = doc.toJson(QJsonDocument::Compact);
    sendRequest(LOGINOUT,true,jsondata);

}

void HttpHelper::slot_AddmediaInfo(const QVariantMap &infomap)
{

    QJsonObject paramsObj;
    paramsObj[""] = QJsonObject();
    QJsonObject rootObj;
    rootObj["createTime"] = "";
    rootObj["updateTime"] = "";
    rootObj["mediaId"] = 0;
    rootObj["params"] = paramsObj;
    rootObj["userId"] = 0;
    rootObj["orderNum"] = 0;
    rootObj["mediaUrl"] = infomap["mediaUrl"].toString();
    rootObj["mediaTitle"] = infomap["mediaTitle"].toString();
    //QJsonObject转为jsondocument
    QJsonDocument doc(rootObj);
    QByteArray jsondata = doc.toJson(QJsonDocument::Compact);
    sendRequest(ADDMEDIA,true,jsondata);
}

void HttpHelper::slot_EditmediaInfo(const QVariantMap &infomap)
{
    QJsonObject paramsObj;
    paramsObj[""] = QJsonObject();
    QJsonObject rootObj;
    rootObj["createTime"] = "";
    rootObj["updateTime"] = "";
    rootObj["mediaId"] = 0;
    rootObj["params"] = paramsObj;
    rootObj["userId"] = 0;
    rootObj["orderNum"] = 0;
    rootObj["mediaUrl"] = infomap["mediaUrl"].toString();
    rootObj["mediaTitle"] = infomap["mediaTitle"].toString();
    //QJsonObject转为jsondocument
    QJsonDocument doc(rootObj);
    QByteArray jsondata = doc.toJson(QJsonDocument::Compact);
    sendRequest(EDITMEDIA,true,jsondata);
}

void HttpHelper::slot_RemovemediaInfo(const QVariantMap &infomap)
{

    QJsonObject paramsObj;
    paramsObj[""] = QJsonObject();
    QJsonObject rootObj;
    rootObj["createTime"] = "";
    rootObj["updateTime"] = "";
    rootObj["mediaId"] = 0;
    rootObj["params"] = paramsObj;
    rootObj["userId"] = 0;
    rootObj["orderNum"] = 0;
    rootObj["mediaUrl"] = infomap["mediaUrl"].toString();
    rootObj["mediaTitle"] = infomap["mediaTitle"].toString();
    //QJsonObject转为jsondocument
    QJsonDocument doc(rootObj);
    QByteArray jsondata = doc.toJson(QJsonDocument::Compact);
    sendRequest(REMOVEMEDIA,true,jsondata);
}

void HttpHelper::HandleReply(const QByteArray &data)
{
   QJsonParseError parseError;
   QJsonDocument jsonDoc=QJsonDocument::fromJson(data,&parseError);
   QByteArray jsonstring=jsonDoc.toJson(QJsonDocument::Indented);
   qDebug()<<"json data:"<<jsonstring.constData();
   //检查解析是否有误
   if(parseError.error !=QJsonParseError::NoError)
   {
       qDebug()<<"JSON解析出错:"<<parseError.errorString()<<"位置:"<<parseError.offset;
       return;
   }
   //
   if(jsonDoc.isObject())
   {
       QJsonObject jsonObj=jsonDoc.object();
       bool operationSuccess=(jsonObj["code"].toInt()==200);
       int reponseType=jsonObj["responseType"].toInt();
       if(reponseType !=MEDIALIST)
       {
           if(reponseType==LOGIN && operationSuccess)
           {
               token=jsonObj["msg"].toString();
           }
           emit sig_Operator(static_cast<REQUESTTYPE>(reponseType),operationSuccess);
       }
       else if(reponseType==MEDIALIST && operationSuccess)
       {
            QJsonValue dataValue=jsonObj["data"];
            //检查data是否为数组
            QVector<QVariantMap> mediaList;
            if(dataValue.isArray())
            {
                QJsonArray dataArray=dataValue.toArray();
                //遍历数组提取里面的视频url和title
                for(const QJsonValue &itemValue : dataArray)
                {
                    if(itemValue.isObject())
                    {
                        QJsonObject itemObj=itemValue.toObject();
                        QVariantMap mediaItem;
                        if(itemObj.contains("mediaTitle")&& itemObj["mediaTitle"].isString())
                        {
                            mediaItem["mediaTitle"].toString();
                        }
                        if(itemObj.contains("mediaUrl")&&itemObj["mediaUrl"].isString())
                        {
                            mediaItem["medaiUrl"]=itemObj["mediaUrl"].toString();
                        }
                        mediaList.append(mediaItem);
                    }
                }
            }
            emit sig_MediaInfo(mediaList);
       }
       if(!operationSuccess)
       {
           qDebug()<<"操作失败:"<<jsonObj["msg"].toString();
       }

   }
}

void HttpHelper::onReplyFinished(QNetworkReply *reply)
{
    //获取HTTP状态码
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    //获取详细错误信息
    QNetworkReply::NetworkError errorType = reply->error();
    QString errorMsg = reply->errorString();
    qDebug()<<"request URL: "<<reply->url().toString();
    qDebug()<<"HTTP status code: "<<statusCode.toInt();
    qDebug()<<"Error Type: "<<errorType;
    qDebug()<<"Error Message: "<<errorMsg;
    QByteArray reponse = reply->readAll();
    qDebug()<<"respose data: "<<QString::fromUtf8(reponse);
    if(errorType == QNetworkReply::NoError){
        //处理应答
        HandleReply(reponse);
    }
    else{
        switch (errorType) {
        case QNetworkReply::ConnectionRefusedError:
            qDebug()<<"连接拒绝,服务都安未启动或者端口未开放";
            break;
        case QNetworkReply::HostNotFoundError:
            qDebug()<<"主机未找到,ip或者DNS错误";
            break;
        case QNetworkReply::TimeoutError:
            qDebug()<<"请求超时";
            break;
        case QNetworkReply::ContentNotFoundError:
            qDebug()<<"连接没有找到，URL错误";
            break;
        default:
            qDebug()<<"其他错误"<<errorMsg;
        }
    }
    reply->deleteLater();
}

void HttpHelper::sendGetRequest(const QNetworkRequest &request)
{
    networkManager->get(request);
}

void HttpHelper::sendPostRequest(QNetworkRequest &request, const QByteArray &data)
{
    networkManager->post(request,data);
}

void HttpHelper::sendRequest(const REQUESTTYPE type, bool isPost, const QByteArray data)
{
    QUrl url = QUrl::fromUserInput(requestAddrs[type]);
    if(!url.isValid()){
        qDebug()<<"url无效";
        return;
    }
    QNetworkRequest request(url);
    //指定数据为json
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
    //设置token
    QByteArray authHeader = token.toUtf8();
    request.setRawHeader("Authorization",authHeader);
    //判断
    isPost ? sendPostRequest(request,data) : sendGetRequest(request);

}


